<template>
  <div
    class="base-image"
    :style="{ width: (props.width) + 'px', height: ( props.height) + 'px', background: (props.bgColor) || 'none' ,borderRadius:(localRadius)+'px' }"
    @click.stop="handleClick"
  >
    <img
      :src="realSrc"
      :key="localSrc"
      :alt="localAlt"
      :style="imgStyle"
      :class="['base-image-img', localImgClass, `img-type-${srcType}`]"
      @load="onLoad"
      @error="onError"
      draggable="false"
    />
    <div v-if="loading" class="base-image-loading">
      <slot name="loading">
        <span>加载中...</span>
        <span style="font-size:12px;color:#888;">({{ srcType }})</span>
        {{ realSrc }}
      </slot>
    </div>
    <div v-else-if="error" class="base-image-error">
      <slot name="error">
        <img :src="localFallback" alt="加载失败" :style="imgStyle" />
      </slot>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, watch, CSSProperties } from 'vue'
import { ComponentInstance } from '@/types/visual-app'
import notFoundImg from '@/assets/img/state/404.png'
import { useDynamicComponentStore } from '@/store/dynamicComponent'
import { axiosInstance } from '@/utils/http/index'
import { transformData} from '@/utils/visual/ConfigUtil'
const BASE_API = axiosInstance.defaults.baseURL
const dynamicComponentStore = useDynamicComponentStore()
const props = defineProps<ComponentInstance>()

const loading = ref(true)
const error = ref(false)

// 本地变量响应 props.config
const localSrc = ref(props.config?.src || notFoundImg)
const localWidth = ref(props.config?.width ?? 200)
const localHeight = ref(props.config?.height ?? 120)
const localRadius = ref(props.config?.radius ?? 0)
const localAlpha = ref(props.config?.alpha ?? 1)
const localCss = ref(props.config?.css ?? '')
const localObjectFit = ref(props.config?.objectFit || 'cover')
const localPreview = ref(props.config?.preview ?? true)
const localFallback = ref(props.config?.fallback || '')
const localAlt = ref(props.config?.alt || '')
const localImgClass = ref(props.config?.imgClass || '')
const localBoxShadow = ref(props.config?.boxShadow || '')
const localTransform = ref(props.config?.transform || '')
const localBindings = ref<any[]>(Array.isArray(props.bindings) ? [...props.bindings] : [])




watch(() => props.config?.src, val => {
  localSrc.value = val || ''
  
  if (!val) {
    localSrc.value = notFoundImg;
  } else if (/^(https?:)?\/\//i.test(val)) {
    localSrc.value = val;
  } else {
    localSrc.value =BASE_API + '/visual/material/image/' + val + '?' + new Date().getTime();
  }
  loading.value = true
  error.value = false
})

const realSrc = computed(() => {
  if (! localSrc.value) {
    return notFoundImg;
  } else if (/^(https?:)?\/\//i.test( localSrc.value)) {
    return  localSrc.value
  } else {
    return BASE_API + '/visual/material/image/' + localSrc.value + '?' + new Date().getTime();
  }
})


watch(() => props.config?.width, val => { localWidth.value = val ?? 200 })
watch(() => props.config?.height, val => { localHeight.value = val ?? 120 })
watch(() => props.config?.radius, val => { localRadius.value = val ?? 0 })
watch(() => props.config?.objectFit, val => { localObjectFit.value = val || 'cover' })
watch(() => props.config?.preview, val => { localPreview.value = val ?? true })
watch(() => props.config?.fallback, val => { localFallback.value = val || '' })
watch(() => props.config?.alt, val => { localAlt.value = val || '' })
watch(() => props.config?.imgClass, val => { localImgClass.value = val || '' })
watch(() => props.config?.alpha, val => { localAlpha.value = val ?? 1 })
watch(() => props.config?.css, val => { localCss.value = val || '' })
watch(() => props.config?.boxShadow, val => { localBoxShadow.value = val || '' })
watch(() => props.config?.transform, val => { localTransform.value = val || '' })



const srcType = computed(() => {
  if (!localSrc.value) return 'empty'
  if (/^data:image\//.test(localSrc.value)) return 'base64'
  if (/^https?:\/\//.test(localSrc.value)) return 'network'
  return 'local'
})

const onLoad = () => {
  loading.value = false
  error.value = false
}
const onError = () => {
  loading.value = false
  error.value = true
}

const emit = defineEmits<{
  (e: 'click', data:any): void
}>()

const handleClick = () => {
	emit('click', props); 
}

const triggerEventMethods=async (eventType: string, ...args: any[]) =>{
  const eventBindings = localBindings.value.filter(
    b => b.event === eventType && b.target && b.targetMethod
  )
  for (const binding of eventBindings) {
    const instance = dynamicComponentStore.getRef(binding.target)
    if (instance && typeof instance.ref[binding.targetMethod] === 'function') {
	  if(binding.params){
		let param=transformData(binding.params,args[0])
		instance.ref[binding.targetMethod](param)
	  }
	  else{
		instance.ref[binding.targetMethod](...args)
	  }
    }
  }
}

const containerStyle = computed(() => ({
  width: typeof localWidth.value === 'number' ? localWidth.value + 'px' : localWidth.value,
  height: typeof localHeight.value === 'number' ? localHeight.value + 'px' : localHeight.value,
  borderRadius: typeof localRadius.value === 'number' ? localRadius.value + 'px' : localRadius.value,
  overflow: 'hidden',
  cursor: localPreview.value ? 'pointer' : undefined,
  ...(props.config?.style || {})
}))

const imgStyle = computed<CSSProperties>(() => {
  const baseStyle: CSSProperties = {
    width: '100%',
    height: '100%',
    backgroundSize: localObjectFit.value as CSSProperties['objectFit'],
    display: 'block',
    opacity: localAlpha.value,
    borderRadius:localRadius.value,
	boxShadow:localBoxShadow.value,
	transform:localTransform.value
  }
  
  // 安全地解析 CSS 配置
  if (localCss.value && localCss.value.trim()) {
    try {
      const cssConfig = JSON.parse(localCss.value)
      if (typeof cssConfig === 'object' && cssConfig !== null) {
        return { ...baseStyle, ...cssConfig }
      }
    } catch (error) {
      console.warn('CSS 配置解析失败:', error)
    }
  }
  
  return baseStyle
})
</script>

<style scoped>
.base-image {
  position: relative;
  display: inline-block;
  /* background: #f5f7fa; */
  user-select: none;
}
.base-image-loading,
.base-image-error {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #bbb;
  font-size: 14px;
  background: rgba(245,247,250,0.85);
  z-index: 2;
}
</style>
